package com.song.registry;

import com.song.enumeration.ResponseCode;
import lombok.extern.slf4j.Slf4j;

import java.net.InetSocketAddress;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 新建一个默认的注册表类 DefaultServiceRegistry 来实现这个接口，提供服务注册服务
 * 根据接口名称 去找到 实现类
 * 向服务端提供多个注册中心
 */
@Slf4j(topic = "c.DefaultServiceRegistry")
public class DefaultServiceRegistry implements ServiceRegistry{

    //将包含注册信息的 serviceMap 和 registeredService 都改成了 static ，
    // 和对象类 一样 存放在方法区内，  这样就能保证全局唯一的注册信息，并且在创建 RpcServer 时也就不需要传入了。

    //将服务名与提供服务的对象的对应关系保存在一个 ConcurrentHashMap 中，
    private static final Map<String, Object> serviceMap = new ConcurrentHashMap<>();

    //并且使用一个 Set 来保存当前有哪些对象已经被注册。
    private static final Set<String> registeredService = ConcurrentHashMap.newKeySet();


    @Override
    public void register(String service, InetSocketAddress inetSocketAddress) {
        log.info("此处为线上注册方式");
        return;
    }

    //注册服务
    @Override
    public synchronized <T> void localRegister(T service) throws Exception {
        String serviceName = service.getClass().getCanonicalName();//返回Java语言规范定义的基础类的规范名称

        //该服务已注册
        if(registeredService.contains(serviceName)) {
            return;
        }

        //添加服务
        registeredService.add(serviceName);

        Class<?>[] interfaces = service.getClass().getInterfaces();
        if(interfaces.length == 0) {//此处表示 服务端注册中心没有找到 客户端传来的 通用HelloService接口
            throw new Exception(String.valueOf(ResponseCode.SERVICE_NOT_IMPLEMENT_ANY_INTERFACE));
        }

        for(Class<?> i : interfaces) {
            serviceMap.put(i.getCanonicalName(), service);
        }
        log.info("向接口：{}注册服务：{}", interfaces,serviceName);//向接口：[interface com.song.api.HelloService]注册服务：com.song.NettyTest.HelloServiceImpl
    }

    //获取服务接口信息
    @Override
    public synchronized Object getService(String serviceName) throws Exception {
        Object service = serviceMap.get(serviceName);
        if(service == null) {//该接口不存在注册中心里面
            throw new Exception(String.valueOf(ResponseCode.SERVICE_NOT_FOUND));
        }
        return service;
    }
}
